#import "CTBaseRequest.h"
#import <AFNetworking/AFNetworking.h>
#import "BaseNetRequest.h"
#import "CTEnvironmentManager.h"
@interface CTBaseRequest ()
@property (nonatomic ,strong) BaseNetRequest *baseRequest;
@end
@implementation CTBaseRequest
#pragma mark - Class method
+(void)postRequestWithMethodName:(NSString *)methodName
                   parametersDic:(NSDictionary *)parametersDic
                         success:(successBlock)success
{
    CTBaseRequest *request = [self initRequestWithMethodName:methodName requestType:RequestTypePost parametersDic:parametersDic];
    [request postRequestSuccess:^(CTBaseRequest *operation, id responseObject) {
        BOOL suc = (operation.requestStatus == RequestStatusSuccess);
        success(operation,suc,responseObject);
    } failure:^(CTBaseRequest *operation, NSError *error) {
        success(operation,NO,operation.resultMessage);
    }];
}
+(void)getRequestWithMethodName:(NSString *)methodName
                  parametersDic:(NSDictionary *)parametersDic
                        success:(successBlock)success
{
    CTBaseRequest *request = [self initRequestWithMethodName:methodName requestType:RequestTypeGet parametersDic:parametersDic];
    [request getRequestSuccess:^(CTBaseRequest *operation, id responseObject) {
        BOOL suc = (operation.requestStatus == RequestStatusSuccess);
        success(operation,suc,responseObject);
    } failure:^(CTBaseRequest *operation, NSError *error) {
        success(operation,NO,operation.resultMessage);
    }];
}
+(void)putRequestWithMethodName:(NSString *)methodName
                  parametersDic:(NSDictionary *)parametersDic
                        success:(successBlock)success
{
    CTBaseRequest *request = [self initRequestWithMethodName:methodName requestType:RequestTypePut parametersDic:parametersDic];
    [request putRequestSuccess:^(CTBaseRequest *operation, id responseObject) {
        BOOL suc = (operation.requestStatus == RequestStatusSuccess);
        success(operation,suc,responseObject);
    } failure:^(CTBaseRequest *operation, NSError *error) {
        success(operation,NO,operation.resultMessage);
    }];
}
+(void)deleteRequestWithMethodName:(NSString *)methodName
                     parametersDic:(NSDictionary *)parametersDic
                           success:(successBlock)success {
    CTBaseRequest *request = [self initRequestWithMethodName:methodName requestType:RequestTypeDelete parametersDic:parametersDic];
    [request deleteRequestSuccess:^(CTBaseRequest *operation, id responseObject) {
        BOOL suc = (operation.requestStatus == RequestStatusSuccess);
        success(operation,suc,responseObject);
    } failure:^(CTBaseRequest *operation, NSError *error) {
        success(operation,NO,operation.resultMessage);
    }];
}
+(void)postImageWithMethodName:(NSString *)methodName
                                 data:(NSData *)data
                              success:(successBlock)success
{
    CTBaseRequest *request = [self initRequestWithMethodName:methodName requestType:RequestTypePost parametersDic:nil];
    request.data = data;
    [request uploadImgRequestSuccess:^(CTBaseRequest *operation, id responseObject) {
        BOOL suc = (operation.requestStatus == RequestStatusSuccess);
        success(operation,suc,responseObject);
    } failure:^(CTBaseRequest *operation, NSError *error) {
        success(operation,NO,operation.resultMessage);
    }];
}
+(void)postImagesArrayWithMethodName:(NSString *)methodName
                                      data:(NSArray <NSData *>*)images
                                   success:(successBlock)success
{
    CTBaseRequest *request = [self initRequestWithMethodName:methodName requestType:RequestTypePost parametersDic:nil];
    request.imageArray = images;
    [request uploadImgArrRequestSuccess:^(CTBaseRequest *operation, id responseObject) {
        BOOL suc = (operation.requestStatus == RequestStatusSuccess);
        success(operation,suc,responseObject);
    } failure:^(CTBaseRequest *operation, NSError *error) {
        success(operation,NO,operation.resultMessage);
    }];
}
- (void)uploadImgRequestSuccess:(void (^)(CTBaseRequest *operation, id responseObject))success
                   failure:(void (^)(CTBaseRequest *operation, NSError *error))failure
{
    [self.baseRequest upLoadWithPOST:_methodName parameters:self.bodyDic image:self.data progress:^(NSProgress * _Nullable progress) {
        NSLog(@"---upload progress：%lld",progress.completedUnitCount/progress.totalUnitCount);
    } success:^(id  _Nonnull responseObject) {
        [self hanleSuccessResponse:responseObject success:success failure:failure];
    } failure:^(NSError * _Nonnull error) {
        [self handlerFailed:failure error:error];
    }];
}
- (void)uploadImgArrRequestSuccess:(void (^)(CTBaseRequest *operation, id responseObject))success
                   failure:(void (^)(CTBaseRequest *operation, NSError *error))failure
{
    [self.baseRequest upLoadWithPOST:_methodName parameters:self.bodyDic imageArray:self.imageArray progress:^(NSProgress * _Nullable progress) {
        NSLog(@"---upload progress：%lld",progress.completedUnitCount/progress.totalUnitCount);
    } success:^(id  _Nonnull responseObject) {
        [self hanleSuccessResponse:responseObject success:success failure:failure];
    } failure:^(NSError * _Nonnull error) {
        [self handlerFailed:failure error:error];
    }];
}
+(CTBaseRequest*)initRequestWithMethodName:(NSString *)methodName
                               requestType:(RequestType)requestType
                               parametersDic:(NSDictionary *)parametersDic
{
    CTBaseRequest *request = [[CTBaseRequest alloc] init];
    request.methodName = methodName;
    if (requestType == RequestTypeGet) {  
    } else {
        [request.bodyDic addEntriesFromDictionary:parametersDic];
    }
    return request;
}
#pragma mark - obj method
- (id)init
{
    self = [super init];
    if (self){
        self.headerDic = [NSMutableDictionary dictionary];
        self.bodyDic = [NSMutableDictionary dictionary];
        self.baseRequest = [BaseNetRequest sharedInstance];
        self.baseRequest.BaseUrl = [CTEnvironmentManager shareManager].environmentUrl;
        [self setDefaultParameter];
        [self signHeader];
    }
    return self;
}
- (void)setDefaultParameter
{
}
- (void)signHeader
{
    [self.baseRequest updateSessionManagerHeaderFields:self.headerDic timeoutInterval:30];
}
#pragma mark  - value
- (void)  setIntegerValue:(NSInteger)value forKey:(NSString *)key
{
    [self setValue:[NSString stringWithFormat:@"%ld", (long)value] forKey:key];
}
- (void)setDoubleValue:(double)value forKey:(NSString *)key
{
    [self setValue:[NSString stringWithFormat:@"%f", value] forKey:key];
}
- (void)setLongLongValue:(long long)value forKey:(NSString *)key
{
    [self setValue:[NSString stringWithFormat:@"%lld", value] forKey:key];
}
- (void)setBOOLValue:(BOOL)value forKey:(NSString *)key
{
    [self setValue:[NSString stringWithFormat:@"%d", value] forKey:key];
}
- (void)setValue:(id)value forKey:(NSString *)key
{
    if(!value){
        return;
    }
    [self.bodyDic setValue:value forKey:key];
}
#pragma mark PrivateMethod
- (BOOL)checkNetReachability
{
    AFNetworkReachabilityStatus status = [AFNetworkReachabilityManager sharedManager].networkReachabilityStatus;
    if  (status!= AFNetworkReachabilityStatusNotReachable) {
        return YES;
    }
    else {
        return NO;
    }
}
#pragma mark - request
- (void)getRequestSuccess:(void (^)(CTBaseRequest *operation, id responseObject))success
                  failure:(void (^)(CTBaseRequest *operation, NSError *error))failure
{
    [self startRequestWithType:RequestTypeGet success:success failure:failure];
}
- (void)postRequestSuccess:(void (^)(CTBaseRequest *operation, id responseObject))success
                   failure:(void (^)(CTBaseRequest *operation, NSError *error))failure
{
    [self startRequestWithType:RequestTypePost success:success failure:failure];
}
- (void)putRequestSuccess:(void (^)(CTBaseRequest *operation, id responseObject))success
                   failure:(void (^)(CTBaseRequest *operation, NSError *error))failure
{
    [self startRequestWithType:RequestTypePut success:success failure:failure];
}
- (void)deleteRequestSuccess:(void (^)(CTBaseRequest *operation, id responseObject))success
                   failure:(void (^)(CTBaseRequest *operation, NSError *error))failure
{
    [self startRequestWithType:RequestTypeDelete success:success failure:failure];
}
#pragma mark - BaseNetRequest
#pragma - Dictionary parameter
- (void)startRequestWithType:(RequestType)type
                     success:(void (^)(CTBaseRequest *operation, id responseObject))success
                     failure:(void (^)(CTBaseRequest *operation, NSError *error))failure
{
    if ([self checkNetReachability]) {
        [self.baseRequest requestWithType:(type?type:RequestTypePost) url:_methodName parameters:_bodyDic success:^(id  _Nonnull responseObject) {
            [self hanleSuccessResponse:responseObject success:success failure:failure];
        } failure:^(NSError * _Nonnull error) {
            [self handlerFailed:failure error:error];
        }];
    }
    else{
        [self handlerFailed:failure error:nil];
    }
}
#pragma - Any parameter
- (void)startRequestWithType:(RequestType)type
                  parameters:(nullable id)parameters
                     success:(void (^)(CTBaseRequest *operation, id responseObject))success
                     failure:(void (^)(CTBaseRequest *operation, NSError *error))failure
{
    if ([self checkNetReachability]) {
        [self.baseRequest requestWithType:(type?type:RequestTypePost) url:_methodName parameters:parameters success:^(id  _Nonnull responseObject) {
            [self hanleSuccessResponse:responseObject success:success failure:failure];
        } failure:^(NSError * _Nonnull error) {
            [self handlerFailed:failure error:error];
        }];
    }
    else{
        [self handlerFailed:failure error:nil];
    }
}
#pragma mark - response
- (void)hanleSuccessResponse:(id)responseObject
                                  success:(void (^)(CTBaseRequest *operation, id responseObject))success
                     failure:(void (^)(CTBaseRequest *operation, NSError *error))failure {
    NSMutableDictionary* resultDic = [NSMutableDictionary dictionary];
    if ([responseObject isKindOfClass:[NSDictionary class]]) {
        resultDic = responseObject;
    }
    else {
        NSData* clearData = responseObject;
        if (clearData) {
            resultDic = (NSMutableDictionary *)clearData;
            if(![resultDic isKindOfClass:[NSDictionary class]]) {
                resultDic = nil;
            }
        }
    }
    if (resultDic && resultDic[@"textualCommunication"]) {
        self.resultMessage = [NSString stringWithFormat:@"%@",resultDic[@"textualCommunication"]];
    }
    BOOL isNormalSuc = (resultDic && [resultDic[@"operationalStatus"] isKindOfClass:[NSNumber class]] && [(NSNumber *)resultDic[@"operationalStatus"] intValue]==0);
    BOOL isReportSuc = (resultDic && [resultDic[@"status"] isKindOfClass:[NSString class]] && [(NSString *)resultDic[@"status"] isEqualToString:@"0"]);
    BOOL isCreditSuc = (resultDic && [resultDic[@"outcomeCode"] isKindOfClass:[NSString class]] && [(NSString *)resultDic[@"outcomeCode"] isEqualToString:@"0000"]);
    if (isNormalSuc || isCreditSuc || isReportSuc) {
        self.isError = NO;
        if (isNormalSuc) {
            self.code = resultDic[@"operationalStatus"];
        }
        if (isReportSuc) {
            self.code = resultDic[@"status"];
        }
        if (isCreditSuc) {
            self.code = resultDic[@"outcomeCode"];
        }
    }
    else {
        self.isError = YES;
        if (resultDic && [resultDic[@"operationalStatus"] isKindOfClass:[NSNumber class]]) {
            NSNumber *status = resultDic[@"operationalStatus"];
            if (status.integerValue == 1015 || status.integerValue == 1016 || status.integerValue == 1617 || status.integerValue == 1618 || status.integerValue == 1619 || status.integerValue == 1014 || status.integerValue == 1010 || status.integerValue == 1017 || status.integerValue == 7006 || status.integerValue == 7007 || status.integerValue == 7008 ) {
                self.showGraphicCode = YES;
            } else {
                self.showGraphicCode = NO;
            }
            if (status.integerValue == 7 || status.integerValue == 15  || status.integerValue == 17 || status.integerValue == 29 || status.integerValue == 2200 || status.integerValue == 100008 || status.integerValue == 100009 || status.integerValue == 8000) {
                [[CTUserManager shareManager] userLogout];
                if (status.integerValue == 7) {
                    [[UIViewController currentViewController].view showText:@"Login has expired, please log in again."];
                } else {
                    [[UIViewController currentViewController].view showText:@"The account has been logged in on another device. To ensure the security of your account, please change your password in time."];
                }
            }
            self.code = [status stringValue] ;
        }
        if (resultDic && [resultDic[@"status"] isKindOfClass:[NSString class]]) {
            self.code = resultDic[@"status"];
        }
        if (resultDic && [resultDic[@"outcomeCode"] isKindOfClass:[NSString class]]) {
            self.code = resultDic[@"outcomeCode"];
        }
    }
    if (!self.isError) {
        self.requestStatus = RequestStatusSuccess;
        success(self, resultDic);
    } else {
        self.requestStatus = RequestStatusFormatError;
        failure(self, nil);
    }
}
- (void)handlerFailed:(void (^)(CTBaseRequest *operation, NSError *error))failure error:(NSError *)error
{
    AFNetworkReachabilityStatus status = [AFNetworkReachabilityManager sharedManager].networkReachabilityStatus;
    if  (status!= AFNetworkReachabilityStatusNotReachable && status!= AFNetworkReachabilityStatusUnknown) {
        self.requestStatus = RequestStatusRemoteFaild;
        if ([error.userInfo valueForKey:@"NSLocalizedDescription"]) {
            NSString *errorMsg = error.userInfo[@"NSLocalizedDescription"];
            if (errorMsg.length) {
                self.resultMessage = @"Network timeout, please try again later!";
            } else {
                self.resultMessage = @"Network timeout, please try again later!";
            }
        } else {
            self.resultMessage = @"Network timeout, please try again later!";
        }
    }
    else{
        self.requestStatus = RequestStatusCanNotReachable;
        self.resultMessage = @"Your network is not working!";
    }
    failure(self, nil);
}
@end
